﻿namespace StyleCop.CSharp
{
    /// <summary>
    /// A base class for StyleCop rules.
    /// </summary>
    /// <typeparam name="TRuleGroup">The type of the rule group.</typeparam>
    /// <remarks>
    /// The StyleCop API seems to push putting a number of rules into a single class. This base class allows making a
    /// single rule per class.
    /// </remarks>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cs", Justification = "That is the name StyleCop uses.")]
    public abstract class CsRuleBase<TRuleGroup>
        where TRuleGroup : SourceAnalyzer
    {
        private readonly TRuleGroup analyzer;
        private CsDocument document;

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="CsRuleBase&lt;TRuleGroup&gt;"/> class.
        /// </summary>
        /// <param name="analyzer">The analyzer.</param>
        protected CsRuleBase(TRuleGroup analyzer)
        {
            this.analyzer = analyzer;
        }
        #endregion Constructors

        #region Public Properties
        /// <summary>
        /// Gets the analyzer.
        /// </summary>
        /// <value>The analyzer.</value>
        public TRuleGroup Analyzer
        {
            get { return this.analyzer; }
        }

        /// <summary>
        /// Gets the document being analyzed.
        /// </summary>
        /// <value>The document being analyzed.</value>
        public CsDocument Document
        {
            get { return this.document; }
            internal set { this.document = value; }
        }
        #endregion Public Properties

        #region Public Methods
        /// <summary>
        /// Adds the violation.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="ruleName">The name of the rule.</param>
        /// <param name="values">The values.</param>
        public void AddViolation(CsElement element, string ruleName, params object[] values)
        {
            this.Analyzer.AddViolation(element, ruleName, values);
        }

        /// <summary>
        /// Adds the violation.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="line">The line number.</param>
        /// <param name="ruleName">The name of the rule.</param>
        /// <param name="values">The values.</param>
        public void AddViolation(CsElement element, int line, string ruleName, params object[] values)
        {
            this.Analyzer.AddViolation(element, line, ruleName, values);
        }

        /// <summary>
        /// Analyzes the document.
        /// </summary>
        public virtual void AnalyzeDocument()
        {
        }

        /// <summary>
        /// Analyzes the graph.
        /// </summary>
        /// <param name="element">The element the graph was built from.</param>
        /// <param name="graph">The graph of the element.</param>
        public virtual void AnalyzeGraph(CsElement element, CodeUnitGraph graph)
        {
        }

        /// <summary>
        /// Cleans up after analyzing the document.
        /// </summary>
        public virtual void CleanUp()
        {
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        public virtual void Initialize()
        {
        }
        #endregion Public Methods
    }
}